package exchange


import (
	"github.com/parnurzeal/gorequest"
	"time"
	"srv/cmc/cap"
	"global/core"
	"global/constants"
	"global/libs/structs"
	"encoding/json"
	"github.com/ngaut/log"
	"fmt"
	"global/model"
	"strconv"
	"strings"
)

type ExchangePairData struct {
	Ctx 		*core.Context
	Client 		*gorequest.SuperAgent
	Key 		string
	IntervalC 	*time.Ticker
}

func NewExchangePairData() cap.InterfaceCmc {
	return &ExchangePairData{
		// 缓存5分钟更新
		IntervalC: 		time.NewTicker(5 * time.Minute),
	}
}

func (e *ExchangePairData) Init(ctx *core.Context) cap.InterfaceCmc {
	e.Ctx = ctx
	e.Client = gorequest.New()
	e.Key = e.Ctx.AccountConfig()
	return e
}

func (e *ExchangePairData) Run() error {

	// 周期执行
	go func() {
		e.handler()
		for t := range e.IntervalC.C {
			_ = t
			e.handler()
		}
	}()
	return nil
}

func (e *ExchangePairData) handler() {

	exchanges, err := model.ExchangeModel.AllEnabled()
	if err != nil {
		log.Errorf("Error: %s", err)
		return
	}

	conn := e.Ctx.GetBaseRedis().Get()
	defer conn.Close()

	for _, exchange := range exchanges {

		newP := make(map[string]model.ExchangePair)
		oldP := make(map[string]model.ExchangePair)

		pairs, err := e.do(strconv.Itoa(exchange.Mid))
		if err != nil {
			log.Errorf("Error: get pair from cmc failed, msg: %s", err)
			continue
		}

		// 整理新获取的交易对信息
		symbols := make([]structs.Symbol, 0)
		for _, v := range pairs.MarketPairs {
			base := strings.ToLower(v.MarketPairBase.CurrencySymbol)
			quote := strings.ToLower(v.MarketPairQuote.CurrencySymbol)
			key := base + quote
			symbols = append(symbols, structs.Symbol{
				From: base,
				To: quote,
			})
			newP[key] = model.ExchangePair{
				ExchangeMid: 		exchange.Mid,
				ExchangeSlug: 		exchange.Slug,
				Symbol: 			fmt.Sprintf("%s_%s", base, quote),
				SymbolBase: 		base,
				SymbolBaseMid: 		v.MarketPairBase.CurrencyId,
				SymbolQuote: 		quote,
				SymbolQuoteMid: 	v.MarketPairQuote.CurrencyId,
				CreateTime: 		time.Now(),
				UpdateTime: 		time.Now(),
			}
		}

		if err := core.SaveExchangePairs(conn, exchange.Slug, symbols); err != nil {
			log.Errorf("Error: save pair to redis failed, slug: %s, err: %s", exchange.Slug, err)
			continue
		}

		if err := core.SaveExchangePairVolume24h(conn, exchange.Slug, pairs); err != nil {
			log.Errorf("Error: save pairs volume failed: %s", err)
			continue
		}

		oldPairs, err := model.ExchangePairModel.Find(exchange.Mid)
		if err != nil {
			log.Errorf("Error: get old pairs filed: %s", err)
			continue
		}

		if len(oldPairs) != 0 {
			for _, v := range oldPairs {
				key := v.SymbolBase + v.SymbolQuote
				oldP[key] = v
			}
		}

		// 对新加入的交易对进行添加，已删除的交易对需要去除
		// 1. 新获取的交易对，原来没有的
		pairsNotExistsInOld := make([]model.ExchangePair, 0)
		for k, v := range newP {
			if _, ok := oldP[k]; !ok {
				pairsNotExistsInOld = append(pairsNotExistsInOld, v)
			}
		}

		// 添加
		if len(pairsNotExistsInOld) > 0 {
			_, err := model.ExchangePairModel.MultiInsert(pairsNotExistsInOld)
			if err != nil {
				log.Errorf("Error: %s", err.Error())
			}
		}

		// 2. 原来有该交易，后来被删除了的
		pairsNotExistsInNew := make([]model.ExchangePair, 0)
		for k, v := range oldP {
			if _, ok := newP[k]; !ok {
				pairsNotExistsInNew = append(pairsNotExistsInNew, v)
			}
		}

		if len(pairsNotExistsInNew) > 0 {
			err := model.ExchangePairModel.Remove(pairsNotExistsInNew)
			if err != nil {
				log.Errorf("Error: %s", err)
			}
		}
	}

}

func (e *ExchangePairData) do(exchangeId string) (*structs.CmcExchangeMarketPairs, error) {
	_, body, errs := e.Client.
		Get(core.GetCmcUrl(e.Ctx.IsDebug(), constants.CmcExchangePairsUrl)).
		Set("X-CMC_PRO_API_KEY", e.Key).
		Query(map[string]interface{} {
			"id": 		exchangeId,
			"limit": 	5000,
			"convert": 	"USD,CNY,BTC",
		}).
		End()

	if len(errs) != 0 {
		return nil, errs[0]
	}

	type bodyData struct {
		Status 		structs.CmcStatus					`json:"status"`
		Data 		structs.CmcExchangeMarketPairs 		`json:"data"`
	}

	var parsedBody bodyData
	err := json.Unmarshal([]byte(body), &parsedBody)

	if err != nil {
		return nil, err
	}

	return &parsedBody.Data, nil
}